﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using wwl.Domain.Entities.Rbac;

namespace wwl.DataAccess.Mappings.Rbac
{
  /// <summary>
  /// 角色权限关联实体映射配置类（EF Core 数据映射）
  /// 负责配置角色权限关联实体与数据库表 rbac_role_permission 之间的映射关系和授权约束
  /// 核心价值：实现角色与权限多对多关系的持久化，构建RBAC权限模型的角色-权限授权链路
  /// 设计目标：确保权限授予的准确性和一致性，支撑灵活的角色权限配置和高效的权限验证
  /// </summary>
  public class RolePermissionMap : IEntityTypeConfiguration<RolePermission>
  {
    /// <summary>
    /// 配置角色权限关联实体的数据库映射细节
    /// </summary>
    /// <param name="builder">实体类型构建器，提供流畅API配置授权关联实体的映射规则</param>
    /// <remarks>
    /// 1. 授权完整性：通过外键约束确保角色和权限引用的有效性，维护授权数据的业务准确性
    /// 2. 唯一性保障：联合唯一约束防止重复的角色权限授权，避免权限授予的冗余和冲突
    /// 3. 性能优化：针对角色查询权限和权限查询角色的双向场景设计高效的索引策略
    /// 4. 级联清理：合理的级联删除设置确保角色或权限删除时授权关系的自动清理
    /// </remarks>
    public void Configure(EntityTypeBuilder<RolePermission> builder)
    {
      // 指定表名：明确映射到 rbac_role_permission 表，保持RBAC模块授权表命名的一致性
      builder.ToTable("rbac_role_permission");

      // 配置主键：使用字符串类型主键，支持UUID等多种ID生成策略
      builder.HasKey(x => x.Id);

      #region 属性映射配置
      // 主键映射：64字符长度与角色和权限主键保持一致，NOT NULL 约束确保授权记录标识完整性
      builder.Property(x => x.Id)
          .HasColumnName("id")
          .HasMaxLength(64)
          .IsRequired();

      // 角色标识映射：关联 rbac_role.id，外键约束确保授权角色的存在性和有效性
      builder.Property(x => x.RoleId)
          .HasColumnName("role_id")
          .HasMaxLength(64)
          .IsRequired();

      // 权限标识映射：关联 rbac_permission.id，外键约束确保授权权限的存在性和有效性
      builder.Property(x => x.PermissionId)
          .HasColumnName("permission_id")
          .HasMaxLength(64)
          .IsRequired();

      // 租户标识映射：64字符长度与角色和权限租户标识保持一致，保障授权关系的租户一致性
      builder.Property(x => x.TenantId)
          .HasColumnName("tenant_id")
          .HasMaxLength(64);

      // 操作类型映射：支持不同类型的权限操作（分配、撤销），灵活定义授权粒度
      // 映射到数据库的 operation_type 字段，VARCHAR(20) 类型，并设置默认值为 'ASSIGN'
      builder.Property(x=>x.OperationType)
        .HasColumnName("operation_type")
        .HasMaxLength(20)
        .HasDefaultValue("ASSIGN")
        .IsRequired();

      // 基础实体属性映射：继承自 BaseEntity 的审计字段和软删除支持
      builder.Property(x => x.CreatedTime)
          .HasColumnName("created_time")
          .IsRequired();

      builder.Property(x => x.UpdatedTime)
          .HasColumnName("updated_time")
          .IsRequired();

      builder.Property(x => x.CreatedBy)
          .HasColumnName("created_by")
          .HasMaxLength(64)
          .IsRequired();

      builder.Property(x => x.Remarks)
          .HasColumnName("remarks")
          .HasColumnType("text");

      builder.Property(x => x.IsDeleted)
          .HasColumnName("is_deleted")
          .HasDefaultValue(false);
      #endregion

      #region 外键关系配置
      // 角色外键关系：建立与角色实体的多对一关系，级联删除确保角色删除时授权记录同步清理
      builder.HasOne(rp => rp.Role)
          .WithMany(r => r.RolePermissions)
          .HasForeignKey(rp => rp.RoleId)
          .OnDelete(DeleteBehavior.Cascade);

      // 权限外键关系：建立与权限实体的多对一关系，级联删除确保权限删除时授权记录同步清理
      builder.HasOne(rp => rp.Permission)
          .WithMany(p => p.RolePermissions)
          .HasForeignKey(rp => rp.PermissionId)
          .OnDelete(DeleteBehavior.Cascade);
      #endregion

      #region 索引配置

      // 租户索引：支持按租户查询角色权限关联关系，优化多租户授权体系隔离场景的查询性能
      builder.HasIndex(x => x.TenantId)
          .HasDatabaseName("ix_rbac_role_permission_tenant_id");

      // 联合唯一约束：确保同一角色不能重复授予同一权限，防止权限授权的重复和配置冲突
      builder.HasIndex(x => new { x.RoleId, x.PermissionId })
          .IsUnique()
          .HasDatabaseName("uk_rbac_role_permission_role_perm");
      #endregion
    }
  }
}